package com.artem.barger.amazon.test;

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * Class aims to solve the following problem:
 * <br>
 * <b>Given an array of n integers, find the sum of the most common integer</b>
 * <br>
 * Proposed solution solves problem within O(n) execution time and O(n) space complexity. 
 * @author artem
 *
 */
public class MostCommonInteger {

	private Map<Integer, Integer> cache = new HashMap<Integer, Integer>( );
	
	private List<Integer> array;
	
	public MostCommonInteger( final List<Integer> array) {
		this.array = array;
	}
	
	public MostCommonInteger( final Integer...array) {
		this.array = Arrays.asList( array);
	}
	
	public int calculateSum( ) {
		initializeCache();
		// Since cache has been initialized need to find the map entry
		// with greatest value
		Entry<Integer, Integer> max = findMaximumEntry( );
		if ( null != max)
			return max.getKey() * max.getValue( );
		return -1;
	}

	private void initializeCache( ) {
		for ( Integer i : array) {
			if ( !cache.containsKey(i)) {
				//Once discovered there is no such key stored in the map
				// initialize cache entry with new key and state counter value to 1.
				cache.put(i, 1);
				continue;
			} 
			Integer counter = cache.get(i) + 1;
			cache.put(i, counter);
		}
	}

	private Entry<Integer, Integer> findMaximumEntry() {
		return Collections.max( cache.entrySet( ), new Comparator<Entry<Integer, Integer>>() {
			@Override
			public int compare(Entry<Integer, Integer> o1,
					Entry<Integer, Integer> o2) {
				return o1.getValue().compareTo(o2.getValue( ));
			}
		});
	}
}
